﻿#region
/* ===============================================
 * 作者：guopeng           时间：2012/2/3 20:21:31
 * 
 * 
 * 类描述：
 * 
 * 
 * =============================================== */
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace CollegeShop.Infrastructure.Entities
{
    public class WhereOption<T>
    {
        private ModityContext<T> context = null;
        /// <summary>
        /// where 条件子句
        /// </summary>
        private List<KeyValuePair<LogicType, string>> sentence = new List<KeyValuePair<LogicType, string>>();
        private Dictionary<WhereOperator, string> mapping = new Dictionary<WhereOperator, string>();
        public WhereOption(ModityContext<T> context)
        {
            this.context = context;
            mapping.Add(WhereOperator.Equal, "=");
            mapping.Add(WhereOperator.GreaterThan, ">");
            mapping.Add(WhereOperator.GreaterThanOrEqual, ">=");
            mapping.Add(WhereOperator.LessThan, "<");
            mapping.Add(WhereOperator.LessThanOrEqual,"<=");
            mapping.Add(WhereOperator.Contain, "in");
        }

        public WhereOption<T> WhereSet<TKey>(Expression<Func<T, TKey>> expression, WhereOperator option, object value)
        {
            if (expression.Body.NodeType != ExpressionType.MemberAccess)
            {
                throw new Exception("表达式错误");
            }
            string column = expression.Body.ToString().Split('.')[1];
            sentence.Add(new KeyValuePair<LogicType, string>(LogicType.Sentence, String.Format("{0} {1} {2}", column, mapping[option], BuildValue(value))));
            return this;
        }

        public WhereOption<T> WhereIn<TKey, TParm>(Expression<Func<T, TKey>> expression, List<TParm> value)
        {
            if (expression.Body.NodeType != ExpressionType.MemberAccess)
            {
                throw new Exception("表达式错误");
            }
            string column = expression.Body.ToString().Split('.')[1];
            sentence.Add(new KeyValuePair<LogicType, string>(LogicType.Sentence, String.Format("{0} {1} {2}", column,"in", BuildValue<TParm>(value))));
            return this;
        }

        public WhereOption<T> And()
        {
            sentence.Add(new KeyValuePair<LogicType, string>(LogicType.Operator, " AND "));
            return this;
        }

        public WhereOption<T> Or()
        {
            sentence.Add(new KeyValuePair<LogicType, string>(LogicType.Operator, " OR "));
            return this;
        }

        public ModityContext<T> End()
        {
            bool isSentence = true;
            for (int i = 0, len = sentence.Count(); i < len; i++)
            {
                if ((sentence[i].Key == LogicType.Sentence) == isSentence) //语句和运算符应该间隔存在
                {
                    isSentence = !isSentence; //下一句应该是另一种
                    if (i == 0)
                    {
                        this.context.wheresentence = "WHERE "; //构建where子句开始
                    }
                    this.context.wheresentence += sentence[i].Value;
                }
                else //如果不是语句和运算符间隔，则表达式错误
                {
                    throw new Exception("表达式错误");
                }
            }
            return this.context;
        }

        enum LogicType
        {
            /// <summary>
            /// 语句
            /// </summary>
            Sentence,
            /// <summary>
            /// 操作符合
            /// </summary>
            Operator
        }
        protected string BuildValue(object value)
        {
            return (value.GetType() != typeof(int) ?
                    value.GetType() == typeof(bool) ? Convert.ToBoolean(value) ? "1" : "0" :
                    String.Format("'{0}'", value) :
                    value).ToString();
        }
        protected string BuildValue<TParm>(List<TParm> value)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("(");
            for (int i = 0, len = value.Count; i < len; i++)
            {
                if (typeof(TParm) == typeof(int))
                {
                    sb.Append(String.Format("{0}", value[i]));
                }
                else
                {
                    sb.Append(String.Format("'{0}'", value[i]));
                }
                if (i != len - 1)
                {
                    sb.Append(",");
                }
            }
            sb.Append(")");
            return sb.ToString();
        }
    }
    public enum WhereOperator
    {
        /// <summary>
        /// >
        /// </summary>
        GreaterThan,
        /// <summary>
        /// >=
        /// </summary>
        GreaterThanOrEqual,
        /// <summary>
        /// ==
        /// </summary>
        Equal,
        /// <summary>
        /// <
        /// </summary>
        LessThan,
        /// <summary>
        /// <=
        /// </summary>
        LessThanOrEqual,
        Contain
    }
   
}
